namespace tuple {
    // 数组合并了相同类型的对象，而元组（Tuple）合并了不同类型的对象。

// 元组起源于函数编程语言（如 F#），这些语言中会频繁使用元组。
// 索引签名的元组 只是为方便识别
    type zks = [a: string, b: number];


    type onlyTu = readonly ['dad', 55, 'fdgfd', false]
    type asdsa = onlyTu[number]
    type sadasd = keyof asdsa
    let tuple: [number, string, boolean, Array<number>, object] = [1, 'zks', true, [25], {}]

    type sdas = typeof tuple
    tuple.push(52)
    console.log(tuple[0], tuple[1], tuple[2]);
    console.log(tuple);
// 元组成员的类型可以添加问号后缀（?），表示该成员是可选的。

    let a: [string, number?] = ['sda', 2];
    let av: [string, number?] = ['sda'];

// 由于元组的成员都是数值索引，即索引类型都是number，所以可以像下面这样读取。
    type Tuple = [string, number, Date];
    type TupleEl = Tuple[number]; // string|number|Date


// 声明函数为元祖
    function distanceFromOrigin([x, y]: [number, number]) {
        return Math.sqrt(x ** 2 + y ** 2);
    }

    let point = [3, 4] as const;

    distanceFromOrigin(point as [number, number]); // 报错
}


// 这段代码的目的是：判断一个类型 T 是否为元组。
type IsTuple<T> = T extends readonly [...infer Elements]
    ? number extends T['length']
        ? false
        : true
    : false
//
//
// ✅ T extends readonly [...infer Elements]
// 这表示：
// 如果 T 是一个数组或元组（无论是否只读），就继续往下判断。
// 并且通过 infer Elements 把它的元素类型推导出来（这个 Elements 本身不使用，只是用来获取 T 是不是数组/元组）。


// ✅ number extends T['length']
// 这是关键判断！
// 普通数组的 length 是 number（不确定是多少）。
// 元组的 length 是一个具体的数值字面量类型（例如 2、3）。
// 所以：
// 普通数组：
// T['length'] 是 number，那么 number extends number → true → 返回 false（不是元组）
// 元组：
// T['length'] 是比如 2，那么 number extends 2 → false → 返回 true（是元组）
//




